#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>

#include <openssl/rsa.h>
#include <openssl/pem.h>

#include <event2/event.h>
#include <event2/util.h>
#include <event2/listener.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#include "cmd.h"
#include "utils.h"

#define KEY_SERVER_PORT 8889

//#define RSA_PUBLIC_KEY_NAME  "clipub.key"
#define RSA_PUBLIC_KEY_NAME  "kusrpub.key"

/*
 * req format: TLV
 *

+---------+---------+-----------+
| T_USRID | L_USRID | 0x20 data |
+---------+---------+-----------+
| T_PUBKEY| L_PUBKEY|  pub key  |
+---------+---------+-----------+
| T_WMAC  |    8    | wlan mac  |
+---------+---------+-----------+
| T_BMAC  |	   8	|   bt mac  |
+---------+---------+-----------+

 */

//RSA *pRsa;
uint8_t g_buffer[8192] = {0};
uint8_t g_recv_buffer[8192] = {0};

static int usage(const char *name)
{
	fprintf(stderr, "%s: [-H ip_addr] [-p port]\n", name);

	return 0;
}

int main(int argc, char *argv[])
{
//	int bits=1024, iret;
//	unsigned long e = RSA_3;
//	FILE *pfpublickey;
//	BIO *bio_pub, *bio;
//	int icount, flen, remain;
//	uint8_t *plain_block;

    int fd;
	int ch;
	struct sockaddr_in sin;
	int port = KEY_SERVER_PORT;
	char *host = "192.168.8.1";
	uint8_t *p = g_buffer;
	int ret;
	uint16_t len;
	struct cmd_hdr *hdr;
	struct req_auth_req *auth_req;

	while ((ch = getopt(argc, argv, "p:H:h")) != -1) {
		switch(ch) {
		case 'p':
			port = atoi(optarg);
			break;
		case 'H':
			host = optarg;
			break;
		case 'h':
			/* fall through */
		default:
			return usage(argv[0]);
		}
	}

	hdr = (struct cmd_hdr *)calloc(1, CMD_HDR_LEN + sizeof(struct req_auth_req));
	auth_req = (struct req_auth_req *)hdr->data;

    fd = socket(AF_INET, SOCK_STREAM, 0);

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	//sin.sin_addr.s_addr = htonl(0);
	//inet_aton("127.0.0.1", &sin.sin_addr);
	inet_aton(host, &sin.sin_addr);
	sin.sin_port = htons(port);

	ret = connect(fd, (struct sockaddr *)&sin, sizeof(sin));
	if (ret) {
        perror("connect failed");
	}

//	if(!(pfpublickey = fopen(RSA_PUBLIC_KEY_NAME, "rb"))) {
//		err("open file [ %s ] error!", RSA_PUBLIC_KEY_NAME);
//		exit(0);
//	}
//	RSA_print_fp(stdout, pRsa, 5);

	auth_req->dwUserID = 0x11223344;
	auth_req->strBTAddress[0] = 0x55;
	auth_req->strBTAddress[1] = 0x55;
	auth_req->strBTAddress[2] = 0x55;
	auth_req->strBTAddress[3] = 0x55;
	auth_req->strBTAddress[4] = 0x55;
	auth_req->strBTAddress[5] = 0x55;

	auth_req->strMACAddress[0] = 0x55;
	auth_req->strMACAddress[1] = 0x55;
	auth_req->strMACAddress[2] = 0x55;
	auth_req->strMACAddress[3] = 0x55;
	auth_req->strMACAddress[4] = 0x55;
	auth_req->strMACAddress[5] = 0x55;


	hdr->bType = CMD_REQ_AUTH_REQ;
	hdr->wLength = sizeof(*auth_req);
    dump(__func__, hdr, CMD_HDR_LEN + sizeof(*auth_req));

    // send to key server, and wait for response.
    ret = send(fd, hdr, CMD_HDR_LEN + sizeof(*auth_req), 0);
    printf("send req len %ld, ret %d\n", p - g_buffer, ret);

    len = recv(fd, g_recv_buffer, 8192, 0);
    printf("receive from server, len %d\n", len);
    dump(__func__, g_recv_buffer, len);


	for (;;) {
		struct req_auth_poll *auth_poll = (struct req_auth_poll *)hdr->data;
		hdr->bType = CMD_REQ_AUTH_POLL;
		hdr->wLength = sizeof(*auth_poll);
		auth_poll->dwUserID = 0x11223344;
		ret = send(fd, hdr, CMD_HDR_LEN + sizeof(*auth_poll), 0);

	    len = recv(fd, g_recv_buffer, 8192, 0);
	    printf("receive from server, len %d\n", len);
	    dump(__func__, g_recv_buffer, len);
		if(len <= 0 || g_recv_buffer[0] == CMD_RSP_AUTH_ACK_KEY)
			break;

		// sleep 3s
		sleep(3);
	}

//	RSA_free(pRsa);
//	fclose(pfpublickey);

    return 0;
}
